home *** CD-ROM | disk | FTP | other *** search
- (*===========================================================================*)
- (* Procedure to send/receive things to the PK-232/PK-87 in host mode *)
- (* *)
- (* Copyright 1988, 1989, 1990, 1991, 1992 by H. Roy Engehausen. All *)
- (* rights reserved. *)
- (* *)
- (*===========================================================================*)
-
- (*===========================================================================*)
- (* Main procedure *)
- (* *)
- (* Parm = 0 -- Data *)
- (* 1 -- Data *)
- (* 2 -- General Poll *)
- (* 3 -- Data Poll *)
- (* 4 -- Link Status Poll *)
- (* 5 -- Data ack poll *)
- (*===========================================================================*)
-
- {$UNDEF DEBUG_232}
-
- PROCEDURE send_recv_232(tnc_cmd_data : BYTE);
-
- LABEL
- busy_loop;
-
- TYPE pk232_out = RECORD
- pk232_soh : CHAR;
- CASE INTEGER OF
- 0 : ( pk232_ctl : BYTE;
- pk232_dat : ARRAY[1..649] OF CHAR);
- 1 : (pk232_str : STRING);
- END;
-
- CONST
- pk232_general_command = $4F; (* General command *)
- pk232_specific_command = $40; (* Specific command to a channel *)
- pk232_specific_data = $20; (* Specific data to a channel *)
- pk232_general_data = $29; (* General command *)
-
- pk232_echo_data = $2F; (* Echoed data -- Not in packet mode *)
- pk232_incoming_data = $30; (* Incoming data w/channel number *)
- pk232_incoming_mon = $3F; (* Incoming monitor data *)
- pk232_incoming_link = $40; (* Link status w/channel number *)
- pk232_incoming_cmd = $4F; (* Command response *)
- pk232_incoming_link2 = $50; (* Link status w/channel number *)
- pk232_incoming_status = $5F; (* Protocol status *)
-
- VAR
- b : BOOLEAN;
- c : CHAR;
- data_switch : BOOLEAN;
- i : BYTE;
- in_index : WORD;
- l_switch : BOOLEAN;
- l_str : STRING[12];
- lock_switch : BOOLEAN;
- look_tcb : tcb_ptr;
- out_index : WORD;
- pk232_buff : ^pk232_out;
- pk232_chan : BYTE;
- pk232_len : INTEGER;
-
- {$I BBSRT23I.PAS} (* I/O Subroutines *)
- {$I BBSRT23D.PAS} (* Decode incoming packet to WA8DED format *)
-
- BEGIN;
-
- (*-----------------------------------------------------------------------*)
- (* Initialize *)
- (*-----------------------------------------------------------------------*)
-
- pk232_buff := @active_tcb^.tnc_htt^;
-
- data_switch := tnc_cmd_data = info_cmd_info;
-
- l_switch := FALSE;
-
- (*-----------------------------------------------------------------------*)
- (* Grab the port lock *)
- (*-----------------------------------------------------------------------*)
-
- WITH active_port^, active_tcb^ DO
- BEGIN;
-
- IF tnc_cmd_data = info_cmd_info THEN
- BEGIN;
-
- (*---------------------------------------------------------------*)
- (* Sending data so we have to wait for the all clear from the TNC*)
- (* before proceeding *)
- (*---------------------------------------------------------------*)
-
- lock_switch := TRUE;
-
- (*---------------------------------------------------------------*)
- (* Loop while we wait *)
- (*---------------------------------------------------------------*)
-
- WHILE lock_switch DO
- BEGIN;
-
- (*-----------------------------------------------------------*)
- (* Lock the port *)
- (*-----------------------------------------------------------*)
-
- get_semaphore(port_sema, sem_exclusive, FALSE);
-
- (*-----------------------------------------------------------*)
- (* See if anyone else is waiting *)
- (*-----------------------------------------------------------*)
-
- IF port_pk232_data_ack THEN
- BEGIN;
-
- (*-------------------------------------------------------*)
- (* Someone else is waiting. Free port and wait *)
- (*-------------------------------------------------------*)
-
- free_semaphore(port_sema);
- FOR i := 1 TO 10 DO
- task_switch;
- END
- ELSE
- BEGIN;
-
- (*-------------------------------------------------------*)
- (* No one else is waiting. Show that we are and let *)
- (* out of loop *)
- (*-------------------------------------------------------*)
-
- port_pk232_data_ack := TRUE;
- lock_switch := FALSE;
-
- END;
-
- END; (*----- End lock switch loop -----------------------------*)
-
- END (*----- End sending data --------------------------------------*)
- ELSE
-
- (*-----------------------------------------------------------------*)
- (* This is a command so we just get the lock *)
- (*-----------------------------------------------------------------*)
-
- get_semaphore(port_sema, sem_exclusive, FALSE);
-
- END; (*---- End addressing --------------------------------------------*)
-
- (*-----------------------------------------------------------------------*)
- (* This is where we loop to on a TNC busy *)
- (*-----------------------------------------------------------------------*)
-
- busy_loop:
-
- (*-----------------------------------------------------------------------*)
- (* Recycle the port lock *)
- (*-----------------------------------------------------------------------*)
-
- free_semaphore(active_port^.port_sema);
- get_semaphore(active_port^.port_sema, sem_exclusive, FALSE);
-
- (*-----------------------------------------------------------------------*)
- (* If this is a poll then we may have pending data already. The *)
- (* tnc_data_queued routine will also dequeue the packet so its ready. *)
- (*-----------------------------------------------------------------------*)
-
- WITH active_tcb^ DO
- IF (tnc_cmd_data > 1) AND (tnc_cmd_data < 5)
- AND (tnc_in_chn <> NIL) THEN
- IF tnc_data_queued THEN
- BEGIN;
- free_semaphore(active_port^.port_sema);
- EXIT;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Prevent execution if requested *)
- (*-----------------------------------------------------------------------*)
-
- WHILE active_tcb^.tcb_stop_tnc_io DO
- task_switch;
-
- (*-----------------------------------------------------------------------*)
- (* Start with an SOH *)
- (*-----------------------------------------------------------------------*)
-
- pk232_buff^.pk232_soh := soh;
-
- (*-----------------------------------------------------------------------*)
- (* See if special poll code *)
- (*-----------------------------------------------------------------------*)
-
- IF tnc_cmd_data > 1 THEN
- WITH pk232_buff^ DO
- BEGIN;
-
- (*-----------------------------------------------------------------*)
- (* Special poll. Issue GG *)
- (*-----------------------------------------------------------------*)
-
- pk232_ctl := pk232_general_command;
- pk232_dat[1] := 'G';
- pk232_dat[2] := 'G';
- pk232_dat[3] := etb;
- pk232_len := 5;
-
- END
- ELSE
- WITH pk232_buff^, active_tcb^ DO
- BEGIN;
-
- (*-----------------------------------------------------------------*)
- (* Send command or data *)
- (*-----------------------------------------------------------------*)
-
- IF tnc_cmd_data = info_cmd_info THEN
- BEGIN;
-
- (*-------------------------------------------------------------*)
- (* Send data *)
- (*-------------------------------------------------------------*)
-
- IF channel > 0 THEN
- pk232_ctl := pk232_specific_data + channel - 1
- ELSE
- pk232_ctl := pk232_general_data;
- data_switch := TRUE;
-
- END
- ELSE
- BEGIN;
-
- (*-------------------------------------------------------------*)
- (* Send command *)
- (*-------------------------------------------------------------*)
-
- IF channel > 0 THEN
- pk232_ctl := pk232_specific_command + channel - 1
- ELSE
- pk232_ctl := pk232_general_command;
-
- (*-------------------------------------------------------------*)
- (* Map DED commands into their PK232 counterparts *)
- (*-------------------------------------------------------------*)
-
- WITH tnc_data DO
- BEGIN;
-
- IF str_data = 'L' THEN (* L = CO *)
- BEGIN;
- str_data := 'CO';
- l_switch := TRUE;
- END
- ELSE
- IF str_data = 'D' THEN (* D = DI *)
- str_data := 'DI'
- ELSE
- IF (str_data[1] = 'C') AND (str_data[2] = ' ') AND
- (LENGTH(str_data) > 2) THEN (* C = CO *)
- str_data[2] := 'O'
- ELSE
- BEGIN;
- str_data[1] := UPCASE(str_data[1]);
- str_data[2] := UPCASE(str_data[2]);
- END;
-
- long_length := LENGTH(str_data);
-
- END; (*----- End addressing of TNC_DATA ---------------------*)
-
- END;
-
- (*-----------------------------------------------------------------*)
- (* Now transfer the data to the buffer inserting the DLE as needed *)
- (*-----------------------------------------------------------------*)
-
- in_index := 0;
- out_index := 0;
-
- WITH tnc_data DO
- WHILE in_index < tnc_data.long_length DO
- BEGIN;
-
- INC(in_index);
- INC(out_index);
- c := long_data[in_index];
- IF (c = soh) OR (c = etb) OR (c = dle) THEN
- BEGIN;
- pk232_dat[out_index] := dle;
- INC(out_index);
- END;
-
- pk232_dat[out_index] := c;
-
- END;
-
- (*-----------------------------------------------------------------*)
- (* Put the ETB on the end *)
- (*-----------------------------------------------------------------*)
-
- pk232_dat[out_index + 1] := etb;
- pk232_len := out_index + 3;
-
- END;
-
- {$IFDEF DEBUG_232}
- WITH pk232_buff^ DO
- WRITELN('Sending =', pk232_ctl, pk232_dat[1],
- pk232_dat[2],
- ORD(pk232_dat[3]));
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Now get the main lock *)
- (*-----------------------------------------------------------------------*)
-
- get_semaphore(semaphore_interrupts, sem_shared, FALSE);
-
- (*-----------------------------------------------------------------------*)
- (* Do the I/O *)
- (*-----------------------------------------------------------------------*)
-
- pk232_io;
-
- {$IFDEF DEBUG_232}
- WITH pk232_buff^ DO
- WRITELN('Recving =', pk232_ctl, pk232_dat[1],
- pk232_dat[2],
- ORD(pk232_dat[3]));
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Free the main lock *)
- (*-----------------------------------------------------------------------*)
-
- free_semaphore(semaphore_interrupts);
-
- task_switch;
-
- (*-----------------------------------------------------------------------*)
- (* If we sent data then loop back to do a poll *)
- (*-----------------------------------------------------------------------*)
-
- IF data_switch AND (tnc_cmd_data = info_cmd_info) THEN
- BEGIN;
- tnc_cmd_data := 5;
- GOTO busy_loop;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Quick sanity check *)
- (*-----------------------------------------------------------------------*)
-
- IF pk232_len < 4 THEN
- window_write_critical_i('Invld PK-232 Len -- '
- + active_tcb^.port_chan_s + ' -- ',
- pk232_len);
-
- (*-----------------------------------------------------------------------*)
- (* Data has arrived *)
- (*-----------------------------------------------------------------------*)
-
- WITH active_tcb^.tnc_data, pk232_buff^ DO
- BEGIN;
-
- (*-------------------------------------------------------------------*)
- (* Decode data as needed *)
- (*-------------------------------------------------------------------*)
-
- pk232_decode;
-
- (*-------------------------------------------------------------------*)
- (* Move data from TNC buffer into data buffer *)
- (*-------------------------------------------------------------------*)
-
- in_index := 0;
- out_index := 0;
- WHILE in_index < (pk232_len-3) DO
- BEGIN;
- INC(in_index);
- INC(out_index);
- c := pk232_dat[in_index];
- IF c = dle THEN
- BEGIN;
- INC(in_index);
- c := pk232_dat[in_index];
- END;
- long_data[out_index] := c;
- END;
-
- long_length := out_index;
- IF long_length > 255 THEN
- str_data[0] := CHR(255)
- ELSE
- str_data[0] := CHR(long_length);
-
- (*-------------------------------------------------------------------*)
- (* OK... Now for the biggy. Did we get data for another channel. *)
- (* The PK232 only has a "general channel poll" so the data could *)
- (* be for anyone. *)
- (*-------------------------------------------------------------------*)
-
- WITH active_tcb^ DO
- IF (pk232_chan <> channel)
- OR ((tnc_cmd_data = 5) AND (long_length <> 0)) THEN
- BEGIN;
-
- (*-------------------------------------------------------------*)
- (* Sanity check for valid channel number *)
- (*-------------------------------------------------------------*)
-
- IF pk232_chan > active_port^.max_chan THEN
- BEGIN;
- window_write_critical_i('Invld chan no from PK-232 -- '
- + port_chan_s + ' -- ',
- pk232_chan);
- pk232_chan := 0;
- END;
-
- (*-------------------------------------------------------------*)
- (* Find out what TCB applies to this channel. If none, use the*)
- (* AUX task *)
- (*-------------------------------------------------------------*)
-
- look_tcb := active_port^.connected^[pk232_chan];
- IF look_tcb = NIL THEN
- look_tcb := active_port^.aux_thread;
-
- (*-------------------------------------------------------------*)
- (* Add info to queue *)
- (*-------------------------------------------------------------*)
-
- {$IFDEF DEBUG_232}
- WRITELN('chaining from ', channel, ' to ', pk232_chan, '/',
- look_tcb^.port_chan_s);
- {$ENDIF}
-
- add_tnc_queue(look_tcb, pk232_chan);
-
- (*-------------------------------------------------------------*)
- (* Go back and poll for this channel again *)
- (*-------------------------------------------------------------*)
-
- GOTO busy_loop;
-
- END;
-
- (*-------------------------------------------------------------------*)
- (* Set null indicator *)
- (*-------------------------------------------------------------------*)
-
- WITH active_tcb^ DO
- tnc_null := long_length = 0;
-
- (*-------------------------------------------------------------------*)
- (* If we are waiting for a data ACK, loop if we didn't get one *)
- (*-------------------------------------------------------------------*)
-
- WITH active_port^ DO
- IF (tnc_cmd_data = 5) AND port_pk232_data_ack THEN
- BEGIN;
- FOR i := 1 TO 10 DO
- task_switch;
- GOTO busy_loop;
- END;
-
- {$IFDEF DEBUG_232}
- WRITELN('NULL=', active_tcb^.tnc_null);
- {$ENDIF}
-
- END; (*---- End WITH for the buffers ----------------------------------*)
-
- (*-----------------------------------------------------------------------*)
- (* Free the port lock *)
- (*-----------------------------------------------------------------------*)
-
- free_semaphore(active_port^.port_sema);
-
- END; (*----- End main send/receive TNC ------------------------------------*)